/**
 * 类描述: minio工具类
 * @since 1.0
 * @author luodeng
 */
package com.system.demo.utils;

import cn.hutool.core.util.ZipUtil;
import io.minio.*;
import io.minio.errors.MinioException;
import io.minio.messages.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Component
public class MinioUtils {

    @Autowired
    private MinioClient minioClient;



    /**
     * 上传文件到MinIO服务器
     *
     * @param file 要上传的文件
     * @param bucketName 桶名
     * @param path 文件保存的路径（不包含文件名）
     * @param objectName 对象名称（即文件名）
     * @return 如果上传成功返回true，否则返回false
     */
    public boolean uploadFile(MultipartFile file, String bucketName, String path, String objectName) {
        try (InputStream inputStream = file.getInputStream()) {
            // 构建完整的对象名称
            String fullObjectName = path + "/" + objectName;

            // 检查存储桶是否存在，如果不存在则创建
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!isExist) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }

            // 上传文件
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fullObjectName)
                            .stream(inputStream, file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build()
            );

            return true;
        } catch (MinioException | IOException | NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
            return false;
        }
    }

    public boolean uploadFile(String file, String bucketName, String path, String objectName) {
        try{
            String fullObjectName = path + "/" + objectName;
            // 检查存储桶是否存在，如果不存在则创建
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!isExist) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }

            // 将字符串转换为字节流
            ByteArrayInputStream inputStream = new ByteArrayInputStream(file.getBytes());

            // 上传文件到MinIO
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fullObjectName)
                            .stream(inputStream, inputStream.available(), -1)
                            .contentType("text/plain")
                            .build()
            );

            System.out.println("文件已成功上传到MinIO。");
            return true;
        }
        catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除MinIO服务器上的文件
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名称（即文件路径和文件名）
     * @return 如果删除成功返回true，否则返回false
     */
    public boolean deleteFile(String bucketName, String objectName) {
        try {
            // 删除文件
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
            return true;
        } catch (MinioException | NoSuchAlgorithmException | InvalidKeyException | IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 检查MinIO服务器上是否存在指定文件
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名称（即文件路径和文件名）
     * @return 如果文件存在返回true，否则返回false
     */
    public boolean isObjectExists(String bucketName, String objectName) {
        try {
            // 检查文件是否存在
            minioClient.statObject(io.minio.StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
            return true;
        } catch (MinioException | NoSuchAlgorithmException | InvalidKeyException | IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 下载MinIO服务器上的文件
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名称（即文件路径和文件名）
     * @return InputStreamResource 包含文件内容的对象
     */
    public InputStreamResource downloadFile(String bucketName, String objectName) {
        try {
            // 获取文件输入流
            InputStream fileStream = minioClient.getObject(
                    GetObjectArgs.builder().bucket(bucketName).object(objectName).build());

            // 返回InputStreamResource对象
            return new InputStreamResource(fileStream);
        } catch (MinioException | NoSuchAlgorithmException | InvalidKeyException | IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 删除文件夹
     *
     * @param bucketName 存储桶名称
     * @param folderPath 要删除的文件夹路径
     */
    public boolean deleteFolder(String bucketName, String folderPath) {
        try {
            // 获取以 folderPath 开头的所有对象
            Iterable<Result<Item>> results = minioClient.listObjects(
                    ListObjectsArgs.builder()
                            .bucket(bucketName)
                            .prefix(folderPath + "/") // 确保只匹配这个文件夹下的对象
                            .recursive(true) // 递归删除所有子目录及其内容
                            .build()
            );

            // 遍历并删除所有匹配的对象
            for (Result<Item> result : results) {
                String objectName = result.get().objectName();
                minioClient.removeObject(
                        RemoveObjectArgs.builder()
                                .bucket(bucketName)
                                .object(objectName)
                                .build()
                );
            }

            return true;
        } catch (MinioException | IOException | NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 得到指定文件的InputStream
     *
     * @param bucketName
     * @param originalName 文件路径
     * @return
     */
    public InputStream getObject(String bucketName, String originalName) {
        try {
            return minioClient.getObject(GetObjectArgs.builder()
            .bucket(bucketName).object(originalName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    public void ZipMultiFileToMinIO(HttpServletResponse response,String bucketName,List<String> fileUrlList,String title) throws IOException {
        //被压缩文件InputStream
        InputStream[] srcFiles = new InputStream[fileUrlList.size()];
        //被压缩文件名称
        String[] srcFileNames = new String[fileUrlList.size()];
        for (int i = 0; i < fileUrlList.size(); i++) {
            String fileUrl = fileUrlList.get(i);
            InputStream inputStream = getObject(bucketName, fileUrl);
            if (inputStream == null) {
                continue;
            }
            srcFiles[i] = inputStream;
            String[] splitFileUrl = fileUrl.split("/");
            srcFileNames[i] = splitFileUrl[splitFileUrl.length - 1];
        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/zip");
        // 编码文件名
        String encodedFileName = URLEncoder.encode(title + ".zip", "UTF-8");
        // 替换 %20 为 空格
        encodedFileName = encodedFileName.replace("+", "%20");
        response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
        //多个文件压缩成压缩包返回
        ZipUtil.zip(response.getOutputStream(), srcFileNames, srcFiles);
    }

}